package top.alanshelby.utils;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import top.alanshelby.service.UserService;
import top.alanshelby.service.impl.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理工具类（用于演示 JDK 动态代理以及 cglib 动态代理）
 */
public class MyProxyUtil {

    public static UserService getProxyByJDK(UserService service) {
        /**
         * Proxy 是 JDK 中的 api
         * 第一个参数：目标对象的类加载器
         * 第二个参数：目标对象的接口
         * 第三个参数：代理对象的执行处理器
         * 注意：使用 JDK 的动态代理目标对象必须是接口
         */
        UserService userService = (UserService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
                service.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("记录日志-开始");
                        // 下面的代码是反射中 API 的用法
                        // 改行代码，实际调用的是目标对象的方法
                        Object obj = method.invoke(service, args);
                        System.out.println("记录日志-结束");
                        return obj;
                    }
                });
        return userService;
    }

    public static UserService getProxyByCglib(UserService service) {
        // 创建增强器
        Enhancer enhancer = new Enhancer();
        // 设置需要增强的类的对象
        enhancer.setSuperclass(UserServiceImpl.class);
        // 设置回调方法
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                long begin = System.currentTimeMillis();
                System.out.println("记录程序开始时间 => " + begin);
                Object object = methodProxy.invokeSuper(o, args);
                long end = System.currentTimeMillis();
                System.out.println("记录程序结束时间 => " + end);
                System.out.println("记录程序运行总时长 => " + (end - begin));
                return object;
            }
        });
        UserService userService = (UserService) enhancer.create();
        return userService;
    }
}
